﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Net;
using DiscogsNet.Api;
using DiscogsNet.Model.Search;

namespace NexTrackDesktop.Media
{
    public interface ITagger
    {
        void tag(Song song);
    }

    /// <summary>
    /// Simple tagger used to tag song information.
    /// </summary>
    public class FileNameTagger : ITagger
    {
        public void tag(Song song)
        {
            // Set the last segment of the "Path" component of the Uri is our fileName if
            // the file is a local file.
            string fileName = Uri.UnescapeDataString(song.Location.Segments.Last());
            song.Album = "Unknown Album";
            song.Artist = "Unknown Artist";
            song.Title = fileName;
            song.Length = new TimeSpan(0, 13, 37);
        }
    }

    /// <summary>
    /// This class contains and tags all Song objects in library
    /// </summary>
    public class TagLibTagger : ITagger
    {
        FileNameTagger fallback = new FileNameTagger();

        /// <summary>
        /// This method tags various song properties
        /// </summary>
        /// <param name="song">Song to tag</param>
        public void tag(Song song)
        {
            try
            {
                TagLib.File tlf = TagLib.File.Create(song.Location.LocalPath);
                song.Album = tlf.Tag.Album;
                song.Artist = tlf.Tag.FirstAlbumArtist;
                song.Length = tlf.Properties.Duration;
                song.Title = tlf.Tag.Title;
            }
            catch
            {
                Debug.Print("Error tagging file " + song.Location);
                fallback.tag(song);
            }
        }
    }

    /// <summary>
    /// This class contains album art tags
    /// </summary>
    public class DiscogsArtTagger : ITagger
    {
        Discogs3 discogs;
        ITagger innerTagger;
        Dictionary<string, Uri> AlbumArtUriCache;
        
        public DiscogsArtTagger(ITagger inner=null)
        {
            discogs = new Discogs3();
            innerTagger = inner;
            AlbumArtUriCache = new Dictionary<string, Uri>();
        }

        /// <summary>
        /// This method tags album art for the specified song.
        /// </summary>
        /// <param name="song">Song to tag album art for</param>
        public void tag(Song song)
        {
            if(innerTagger != null)
                innerTagger.tag(song);

            string CacheKey = string.Format("{0}##{1}#", song.Artist, song.Album);

            if (!AlbumArtUriCache.ContainsKey(CacheKey))
                AlbumArtUriCache[CacheKey] = SearchArt(song.Artist, song.Album);

            song.AlbumArtSource = AlbumArtUriCache[CacheKey];
        }

        /// <summary>
        /// This method searches web (discogs) for album art.
        /// </summary>
        /// <param name="Artist">Song artist</param>
        /// <param name="Album">Song album</param>
        /// <returns>Uri to specified Song album art</returns>
        public Uri SearchArt(string Artist, string Album)
        {
            //note that the discogs search "title" field corresponds
            // to a "release title" aka "album".
            SearchQuery sq = new SearchQuery()
            {
                Artist = Artist,
                Title = Album,
                Type = SearchItemType.Master
            };

            try
            {
                var topResult = discogs.Search(sq).Results.FirstOrDefault();
                return topResult == null ? null : new Uri(topResult.Thumb);
            }
            catch (WebException we)
            {
                return null;
            }
        }
    }
}
